#pragma strict

var explosionSound : AudioClip;
var fireSound : AudioClip;
var projectile : GameObject;

private var explosionAudioSource : AudioSource;
private var fireAudioSource : AudioSource;
private var playerGObj : GameObject;
private var scriptsGObj : GameObject;
private var playerTank : GameObject;
private var groundGObj : GameObject;

private var shootTime : float = 0.5;
private var shootTimer : float = shootTime;
private var moveTime : float = 5.0;
private var moveTimer : float = moveTime; 
private var moveAngle : float = 90.0;
private var switcher = false;
private var audioVolume = 1;

private var speed :int = 100;
private var mass :int = 10;
private var drag :int = 0;
private var startTime : float;

private var fireRate = 3.0;
 private var nextFire = 0.0;

//Awake is before Start
function Awake(){
	explosionAudioSource = gameObject.AddComponent(AudioSource);
	explosionAudioSource.clip = explosionSound;
	explosionAudioSource.loop = false;
	explosionAudioSource.volume = audioVolume;
	explosionAudioSource.playOnAwake = false; //Abspielen wenn es initialisiert wird
	
	fireAudioSource = gameObject.AddComponent(AudioSource);
	fireAudioSource.clip = fireSound;
	fireAudioSource.loop = false;
	fireAudioSource.volume = audioVolume;
	fireAudioSource.playOnAwake = false; //Abspielen wenn es initialisiert wird
}

function Start () {
	scriptsGObj = GameObject.FindGameObjectWithTag("Scripts");
	playerGObj = GameObject.Find("Main Camera");
	playerTank = GameObject.Find("PlayerTank");
	groundGObj = GameObject.Find("Ground");	
	
	// Debug.Log("Spawn position"+transform.position);
	startTime = Time.time;
}

function Update () {
	if(playerTank != null){
		tankMovement(playerTank.transform);
	}else{
		playerTank = GameObject.Find("PlayerTank");	
	}
	
}

private var targetIsHit : boolean;
// Stores the next way point based on the last reached waypoint in world space.
private var nextWaypoint : Vector3;
private var waypointIndex: int = 0;

public function tankMovement (target : Transform) {
//	Debug.Log("tankMovement with target "+target.gameObject.name);

	var lineOfSight = 100;
	var lineOfFire = 50;
	var tankSpeed = 20;
	var minimalDistanceToTarget = 40;
	var rotationSpeed = 50;
	var fov = 90.0; // field of view (angle)
	var hit : RaycastHit;
	var distanceToTarget = Vector3.Distance(target.position, this.transform.position);
	// Calculate the angle between the vector which points forward and the vector which points torwards the target - Is the target in the fov?
	var angleToTarget = Vector3.Angle(target.position - this.transform.position, transform.forward);
	Debug.DrawLine(nextWaypoint,transform.position,Color.red);	
	//	Debug.Log("angleToTarget is " + angleToTarget);
	// Create a Linecast between us and the target - Can we hit the target?
	var hitTest = Physics.Linecast(transform.position, target.position, hit);
	// Check what was hit by the Linecast
	
	// Is the enemy in our field of view?
	if(angleToTarget <= fov) {
		// Is the enemy in our line of sight?
		if(distanceToTarget <= lineOfSight) {
			// Do we hit someting between us and the enemy?
			if(hitTest) {
				// Do we target our enemy?
				if(hit.transform.gameObject == target.gameObject) {
					// Do we directly face our enemy? angleToTarget [0:180]
					if(angleToTarget != 0.0) {
						transform.LookAt(target.position);
						// smooth turn into enemy direction
					}else{
						// drive into enemy direction
						if(distanceToTarget > minimalDistanceToTarget) {
							rigidbody.velocity = transform.TransformDirection(Vector3(0,0, tankSpeed));
						}else{
							rigidbody.velocity = Vector3(0,0,0);
						}
						
						// are we ready to shoot
						if(distanceToTarget <= lineOfFire) {
							// kill'em
						  if (Time.time > nextFire) {
            					nextFire = Time.time + fireRate;
            					shoot();
        					}
						}
					}
				}
				
				// something else was hit, we want to drive around it
				// calculate vector between us and hit.transform
				// determine side of this axsis we are on push us to the shorter side
				
			}else{
				Debug.Log("target is in fov but nothing was hit");
			}
		}else{
			// Target is far away, we don't see it, therefore we do nothing special.
			driveToNextWayPoint(tankSpeed,target);
		}
	}else{ // No target is in fov, so we search for enemies.
		driveToNextWayPoint(tankSpeed,target);
	}
}


function driveToNextWayPoint(tankSpeed : int, target:Transform) {
// use the ground boundary to make sure the tanks stay in

	var gp = groundGObj.transform.position;
	/**
	 * var pos1 = Vector3(gp.x-300,0,gp.z-300); // right upper corner
	 * var pos2 = Vector3(gp.x+300,0,gp.z+300); // left down corner
	 * var pos3 = Vector3(gp.x+300,0,gp.z-300); // left upper corner
	 * var pos4 = Vector3(gp.x-300,0,gp.z+300); // right down corner
	 */
	var enemypos   = target.position;
	    enemypos.y = 0;
	var distance = 200;
	// zigzag pattern which returns to enemy position
	var logicalWaypoints = [ enemypos , transform.right * -1.0*distance, transform.right * -1.0*distance,
							 transform.right*distance, transform.right*distance];
	// first waypoint must be initialized
	if(nextWaypoint == Vector3(0,0,0)) {
	 	nextWaypoint = enemypos;
	 	transform.LookAt(enemypos);
	 }
	 
	var distanceToWaypoint = Vector3.Distance(transform.position, nextWaypoint);
	transform.LookAt(nextWaypoint);
	var distanceToTarget = Vector3.Distance(target.position, transform.position);
	
	if(nextWaypoint.x >= gp.x+500 || nextWaypoint.x <= gp.x-500) {
		// we need to set a new waypoint
		nextWaypoint.x = gp.x;
	}
	if(nextWaypoint.z >= gp.z+500 || nextWaypoint.z <= gp.z-500) {
		// we need a set waypoint
		nextWaypoint.z = gp.z;
	}
	
	// is the currentWaypoint in worldspace reached?
	if(distanceToWaypoint <= 1.0 ) {
		// we are close to the waypoint
		waypointIndex += 1;
	 	// is there another waypoint? if not we start over at the beginning
	 	if(waypointIndex >= logicalWaypoints.Length) waypointIndex = 0;
	 	// calculate the next waypoint
	 	nextWaypoint = transform.position + (logicalWaypoints[waypointIndex]);
	}else{
		// drive to the waypoint, while turning?!
		rigidbody.velocity = transform.TransformDirection(Vector3(0,0, tankSpeed));
	}
}

function OnCollisionEnter (collision : Collision){
	
	if(collision.gameObject.tag == "Projectile" && switcher == false){
		switcher = true;
		
		//Increase playerscore in Class Player
		scriptsGObj.SendMessage("increasePlayerScore", 1);
		
		explosionAudioSource.Play();
		
		//TODO Tank Destroy Animation
	    Destroy(this.gameObject, 0.0);
	}
}

public function shoot(){
	// Shoot from the tank position
	// var spawnPositionProjectile = transform.position; // unused
	
	// Fire in viewing direction of the tank.
	// var spawnRotationProjectile : Quaternion = transform.rotation; // unused
	
	// Instantiate a bullet in front of the tank and shoot in the direction of the player.
	var go : GameObject = Instantiate(projectile, transform.position , transform.rotation);
		go.rigidbody.mass = mass;
		go.rigidbody.drag = drag;
		go.rigidbody.transform.position = transform.TransformPoint(Vector3(0,0.7,5));
		go.rigidbody.transform.localScale = Vector3(0.3,0.3,0.3); //Important to get back in the local system
		go.rigidbody.velocity = transform.TransformDirection(Vector3(0, 0, speed));

		fireAudioSource.Play();

		Destroy(go, 4);
}